home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-09-27 | 36.2 KB | 1,195 lines |
- diff -u -r -N netboot-freebsd-for-linux/3c509.c netboot-freebsd/3c509.c
- --- netboot-freebsd-for-linux/3c509.c Thu Sep 7 18:58:35 1995
- +++ netboot-freebsd/3c509.c Wed Sep 27 20:26:11 1995
- @@ -526,7 +526,8 @@
-
- for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
- if (i >= MAX_EEPROMBUSY) {
- - printf("3c509: eeprom failed to come ready.\r\n");
- + /* printf("3c509: eeprom failed to come ready.\r\n"); */
- + printf("3c509: eeprom is busy.\r\n"); /* memory in EPROM is tight */
- return (0);
- }
- return (1);
- diff -u -r -N netboot-freebsd-for-linux/Makefile netboot-freebsd/Makefile
- --- netboot-freebsd-for-linux/Makefile Sat Sep 9 16:15:10 1995
- +++ netboot-freebsd/Makefile Wed Sep 27 18:57:56 1995
- @@ -6,6 +6,14 @@
- # -DASK_BOOT - Ask "Boot from Network (Y/N) ?" at startup
- # -DROMSIZE - Size of EPROM - Must be set (even for .COM files)
- # -DRELOC - Relocation address (usually 0x90000)
- +# ^^^^^^^
- +# has to be changed to 0x9A000 for loading Linux kernel
- +# -DPRIORIZEBOOTPKERNEL
- +# - first honor the kernel name of the BOOTP reply
- +# before trying defaults
- +# -DBOOTPKERNELONLY
- +# - never use TFTP for loading default files; the
- +# BOOTP reply has to set a valid kernel name
- #
- # NS8390 Options:
- # -DINCLUDE_WD - Include Western Digital/SMC support
- @@ -21,7 +29,7 @@
-
- PROG= nb8390.com nb3c509.com nb8390.rom nb3c509.rom
- # Order is very important on the SRCS line for this prog
- -SRCS= start2.S main.c misc.c bootmenu.c rpc.c
- +SRCS= start2.S main.c linuxloader.c misc.c bootmenu.c rpc.c
-
- BINDIR= /usr/mdec
- BINMODE= 555
- @@ -37,7 +45,7 @@
- STRIP=
-
- ROMSIZE=16384
- -RELOCADDR=0x90000
- +RELOCADDR=0x9A000
-
- .SUFFIXES: .ro
-
- diff -u -r -N netboot-freebsd-for-linux/Makefile.linux netboot-freebsd/Makefile.linux
- --- netboot-freebsd-for-linux/Makefile.linux Sat Sep 9 00:23:05 1995
- +++ netboot-freebsd/Makefile.linux Wed Sep 27 20:30:27 1995
- @@ -6,6 +6,14 @@
- # -DASK_BOOT - Ask "Boot from Network (Y/N) ?" at startup
- # -DROMSIZE - Size of EPROM - Must be set (even for .COM files)
- # -DRELOC - Relocation address (usually 0x90000)
- +# ^^^^^^^
- +# has to be changed to 0x9A000 for loading Linux kernel
- +# -DPRIORIZEBOOTPKERNEL
- +# - first honor the kernel name of the BOOTP reply
- +# before trying defaults
- +# -DBOOTPKERNELONLY
- +# - never use TFTP for loading default files; the
- +# BOOTP reply has to set a valid kernel name
- #
- # NS8390 Options:
- # -DINCLUDE_WD - Include Western Digital/SMC support
- @@ -22,12 +30,13 @@
-
- PROG= nb8390.com nb3c509.com nb8390.rom nb3c509.rom
- # Order is very important on the SRCS line for this prog
- -SRCS= start2.S main.c misc.c bootmenu.c rpc.c
- -OBJS= start2.o main.o misc.o bootmenu.o rpc.o
- -ROBJS= start2.ro main.o misc.o bootmenu.o rpc.o
- +SRCS= start2.S main.c linuxloader.c misc.c bootmenu.c rpc.c
- +OBJS= start2.o main.o linuxloader.o misc.o bootmenu.o rpc.o
- +ROBJS= start2.ro main.o linuxloader.o misc.o bootmenu.o rpc.o
-
- CFLAGS= -O2 -DNFS -DROMSIZE=${ROMSIZE} -DRELOC=${RELOCADDR}
- CFLAGS+= -fstrength-reduce -fomit-frame-pointer -m386
- +CFLAGS+= -DPRIORIZEBOOTPKERNEL
- # NS8390= -DINCLUDE_WD -DWD_DEFAULT_MEM=0xD0000
- NS8390+= -DINCLUDE_NE
- # NS8390+= -DINCLUDE_3COM -D_3COM_BASE=0x300
- @@ -37,7 +46,7 @@
- LDFLAGS+= -N -Ttext ${RELOCADDR} -e _start -nostdlib
-
- ROMSIZE=16384
- -RELOCADDR=0x90000
- +RELOCADDR=0x9A000
-
- .SUFFIXES: .ro
-
- @@ -60,26 +69,22 @@
-
- nb8390.rom: makerom start2.ro ${ROBJS} ns8390.o
- ${LD} ${LDFLAGS} -o nb8390.bin ${ROBJS} ns8390.o
- - strip nb8390.bin
- size nb8390.bin
- objdump -k -q -o ${RELOCADDR} nb8390.bin >$@
- ./makerom $@
-
- nb3c509.rom: makerom start2.ro ${ROBJS} 3c509.o
- ${LD} ${LDFLAGS} -o nb3c509.bin ${ROBJS} 3c509.o
- - strip nb3c509.bin
- size nb3c509.bin
- objdump -k -q -o ${RELOCADDR} nb3c509.bin >$@
- ./makerom $@
-
- nb8390.com: makerom start2.ro ${OBJS} ns8390.o
- ${LD} ${LDFLAGS} -o nb8390c.bin ${OBJS} ns8390.o
- - strip nb8390c.bin
- size nb8390c.bin
- objdump -k -q -o ${RELOCADDR} nb8390c.bin >$@
-
- nb3c509.com: start2.o ${OBJS} 3c509.o
- ${LD} ${LDFLAGS} -o nb3c509c.bin ${OBJS} 3c509.o
- - strip nb3c509c.bin
- size nb3c509c.bin
- objdump -k -q -o ${RELOCADDR} nb3c509c.bin >$@
- diff -u -r -N netboot-freebsd-for-linux/bootmenu.c netboot-freebsd/bootmenu.c
- --- netboot-freebsd-for-linux/bootmenu.c Thu Sep 7 18:58:35 1995
- +++ netboot-freebsd/bootmenu.c Tue Sep 26 11:34:42 1995
- @@ -7,6 +7,7 @@
- **************************************************************************/
- #include "netboot.h"
-
- +extern char *linux_add_cmdline();
- extern struct nfs_diskless nfsdiskless;
- extern int hostnamelen;
- extern unsigned long netmask;
- @@ -16,14 +17,14 @@
- int cmd_ip(), cmd_server(), cmd_kernel(), cmd_help(), exit();
- int cmd_rootfs(), cmd_swapfs(), cmd_interface(), cmd_hostname();
- int cmd_netmask(), cmd_swapsize(), cmd_swapopts(), cmd_rootopts();
- -int cmd_aui();
- +int cmd_linuxcmd(),cmd_aui();
-
- struct bootcmds_t {
- char *name;
- int (*func)();
- char *help;
- } bootcmds[] = {
- - {"?", cmd_help, " this list"},
- +/* {"?", cmd_help, " this list"}, */
- {"help", cmd_help, " this list"},
- {"ip", cmd_ip, "<addr> set my IP addr"},
- {"server", cmd_server, "<addr> set TFTP server IP addr"},
- @@ -35,6 +36,7 @@
- {"swapsize", cmd_swapsize, "<nblks> set swap size"},
- {"swapopts", cmd_swapopts, "<options> swap mount options"},
- {"rootopts", cmd_rootopts, "<options> root mount options"},
- + {"linuxcmd", cmd_linuxcmd, "<cmds> pass cmds to linux"},
- {"diskboot", exit, " boot from disk"},
- {"autoboot", NULL, " continue"},
- {"trans", cmd_aui, "<on|off> turn transceiver on|off"},
- @@ -145,11 +147,11 @@
- {
- if (!setip(p, &arptable[ARP_ROOTSERVER].ipaddr)) {
- printf("Root filesystem is %I:%s\r\n",
- - nfsdiskless.root_saddr.sin_addr,
- + htonl(nfsdiskless.root_saddr.sin_addr.s_addr),
- nfsdiskless.root_hostnam);
- } else {
- - bcopy(&arptable[ARP_ROOTSERVER].ipaddr,
- - &nfsdiskless.root_saddr.sin_addr, 4);
- + convert_ipaddr(&nfsdiskless.root_saddr.sin_addr,
- + &arptable[ARP_ROOTSERVER].ipaddr);
- while (*p && (*p != ':')) p++;
- if (*p == ':') p++;
- sprintf(&nfsdiskless.root_hostnam, "%s", p);
- @@ -164,11 +166,11 @@
- {
- if (!setip(p, &arptable[ARP_SWAPSERVER].ipaddr)) {
- printf("Swap filesystem is %I:%s\r\n",
- - nfsdiskless.swap_saddr.sin_addr,
- + htonl(nfsdiskless.swap_saddr.sin_addr.s_addr),
- nfsdiskless.swap_hostnam);
- } else {
- - bcopy(&arptable[ARP_SWAPSERVER].ipaddr,
- - &nfsdiskless.swap_saddr.sin_addr, 4);
- + convert_ipaddr(&nfsdiskless.swap_saddr.sin_addr,
- + &arptable[ARP_SWAPSERVER].ipaddr);
- while (*p && (*p != ':')) p++;
- if (*p == ':') p++;
- sprintf(&nfsdiskless.swap_hostnam, "%s", p);
- @@ -269,6 +271,19 @@
- }
-
- /**************************************************************************
- +LINUXCMD - Pass commands to linux
- +**************************************************************************/
- +cmd_linuxcmd(p)
- + char *p;
- +{
- + if (*p)
- + linux_add_cmdline(p);
- + else
- + printf("Linux cmdline: %s\r\n",linux_add_cmdline(p));
- + return;
- +}
- +
- +/**************************************************************************
- EXECUTE - Decode command
- **************************************************************************/
- execute(buf)
- @@ -289,7 +304,7 @@
- } else
- cmd++;
- }
- - printf("bad command - type 'help' for list\n\r");
- + printf("error: `help' for list\n\r");
- return(0);
- }
-
- @@ -298,13 +313,19 @@
- **************************************************************************/
- bootmenu()
- {
- + unsigned long time;
- char cmd[80];
- int ptr, c;
- - printf("\r\n");
- + linux_add_cmdline(0); /* clear linux cmdline */
- + printf(" \r\n");
- while (1) {
- ptr = 0;
- printf("boot> ");
- while (ptr < 80) {
- + for (time = currticks() + 90*18; !iskey() ;)
- + if (time < currticks()) {
- + printf("autoboot\r\n");
- + goto done; }
- c = getchar();
- if (c == '\r')
- break;
- @@ -322,5 +343,6 @@
- printf("\r\n");
- if (execute(cmd)) break;
- }
- + done:
- eth_reset();
- }
- diff -u -r -N netboot-freebsd-for-linux/linuxloader.c netboot-freebsd/linuxloader.c
- --- netboot-freebsd-for-linux/linuxloader.c Thu Jan 1 01:00:00 1970
- +++ netboot-freebsd/linuxloader.c Wed Sep 27 19:44:28 1995
- @@ -0,0 +1,271 @@
- +/**************************************************************************
- +Linux loader
- +
- +Author: Markus Gutschke (gutschk@math.uni-muenster.de)
- + Date: Sep/95
- +
- +**************************************************************************/
- +
- +#include "netboot.h"
- +
- +#define LINUX_IMAGE_ADDR ((char *)0x10000L)
- +#define XTRACMDS ((char *)0x98000L)
- +#define LINUX_BOOTSECTOR ((char *)0x90000L)
- +#define CMDLINEMAGIC 0xA33F
- +#define CMDLINE ((unsigned short *)(LINUX_BOOTSECTOR+0x20))
- +#define BOOTHEADER (((boot_header_t *)0x90200L)[-1])
- +#define SECTOR_SIZE 512
- +#define MAGIC 0xAA55
- +#define SETUP_MAGIC 0x5A5AAA55
- +
- +typedef struct {
- + unsigned char filler;
- + unsigned char setup_sects;
- + unsigned short int root_flags;
- + unsigned short int syssize;
- + unsigned short int swap_dev;
- + unsigned short int ram_size;
- + unsigned short int vid_mode;
- + unsigned short int root_dev;
- + unsigned short int boot_flag;
- +} boot_header_t;
- +
- +char *bootphdr = (char *)0x99000L;
- +
- +char *linux_add_cmdline(char *s)
- +{
- + if (!s) *XTRACMDS = '\000';
- + else if (*s) {
- + char *ptr = XTRACMDS;
- + while (*ptr) ptr++;
- + *ptr++ = ' ';
- + sprintf(ptr,"%s",s); }
- + return(XTRACMDS);
- +}
- +
- +static int strncmp(const unsigned char *s1,const unsigned char *s2,int n)
- +{
- + while (n--) {
- + if (*s1 != *s2) return(*s1 - *s2);
- + else if (!*s1) return(0);
- + else {s1++; s2++;}}
- + return(0);
- +}
- +
- +static void linux_cmdline(char *cmdline)
- +{
- + extern char *kernel;
- + extern struct nfs_diskless nfsdiskless;
- + extern unsigned long netmask;
- + char *s,*d,initargs = 0;
- +
- + for (s = XTRACMDS; ;) { /* check for parameters to init */
- + if ((!*s || *s == ' ') && (initargs&1)) initargs = 2;
- + if (!*s) break;
- + if (*s == '=') {initargs &= ~1; while (*s && *s != ' ') s++;}
- + else if (*s++ != ' ') {
- + if (!(initargs&1) && !strncmp(s-1,"vga=",4)) {
- + int vga = 0;
- + d = s + 3;
- + if (!strncmp(d,"ASK",3)) vga = -3;
- + else if (!strncmp(d,"EXTENDED",8)) vga = -2;
- + else if (!strncmp(d,"NORMAL",6)) vga = -1;
- + else {
- + if (*d == '-') d++;
- + while (*d >= '0' && *d <= '9') { vga = 10*vga+*d-'0'; d++; }
- + if (s[3] == '-') vga = -vga; }
- + *((unsigned short *)(LINUX_BOOTSECTOR+506)) = vga; }
- + initargs |= 1; } }
- + for (s = nfsdiskless.root_hostnam;*s&&s[1];s++);
- + sprintf(cmdline,
- + "%sBOOT_IMAGE=" /* %I: */ "%s%s%s ramdisk=0 "
- + "nfsroot=%s,rsize=%d,wsize=%d,%s,%s "
- + "nfsaddrs=%I:%I:%I:%I:%s %s",
- + initargs&2 ? "" : "auto ",
- + /* htonl(nfsdiskless.root_saddr.sin_addr.s_addr), */
- + nfsdiskless.root_hostnam,
- + *s == '/' ? "" : "/",
- + *kernel == '/' ? kernel + 1 : kernel,
- + nfsdiskless.root_hostnam,
- + nfsdiskless.root_args.rsize,
- + nfsdiskless.root_args.wsize,
- + nfsdiskless.root_args.flags & NFSMNT_SOFT ? "soft" : "hard",
- + nfsdiskless.root_args.flags & NFSMNT_INT ? "intr" : "nointr",
- + arptable[ARP_CLIENT].ipaddr,
- + htonl(nfsdiskless.root_saddr.sin_addr.s_addr),
- + arptable[ARP_GATEWAY].ipaddr,
- + htonl(netmask),
- + nfsdiskless.my_hostnam,
- + XTRACMDS);
- + for (s = d = cmdline; ;) { /* remove multiple space characters */
- + if (*s == ' ') {while (s[1] == ' ') s++; if (!s[1]) s++;}
- + if (!(*d++ = *s++)) break; }
- + *((unsigned short *)(LINUX_BOOTSECTOR+504)) = 0; /* no ramdisk */
- + *((unsigned short *)(LINUX_BOOTSECTOR+508)) = 0x00FF; /* mount root on nfs */
- + return;
- +}
- +
- +int load_linux(int root_mount_port,int swap_mount_port,
- + int root_nfs_port,char *kernel_handle)
- +{
- + extern int jmp_bootmenu[10];
- + extern char *kernel;
- + extern void start_linux(void);
- + int err, offset, read_size, count;
- + char *addr,*cmdline;
- +
- + /* Linux boot sector and setup code has to be loaded to address 0x90000 */
- + if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, kernel_handle, 0,
- + SECTOR_SIZE,LINUX_BOOTSECTOR)) != SECTOR_SIZE) {
- + readerr:
- + printf("Unable to read %s: ",kernel);
- + nfs_err(err);
- + bootmenu:
- + longjmp(jmp_bootmenu,1);
- + }
- + if (BOOTHEADER.boot_flag != MAGIC)
- + return(0);
- + /* Boot sector contains size information for setup code */
- + offset = SECTOR_SIZE;
- + read_size = SECTOR_SIZE;
- + count = BOOTHEADER.setup_sects;
- + while (count--) {
- + if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, kernel_handle,
- + offset, read_size, LINUX_BOOTSECTOR + offset)) !=
- + read_size) {
- + if (err < 0) {
- + goto readerr; }
- + goto bootmenu; }
- + offset += err; }
- + for (count = SECTOR_SIZE-4; *(unsigned int *)(LINUX_BOOTSECTOR-
- + SECTOR_SIZE+offset+count) !=
- + SETUP_MAGIC;)
- + if (count-- < 0)
- + goto bootmenu;
- + /* Construct Linux's command line */
- + cmdline = LINUX_BOOTSECTOR + offset;
- + CMDLINE[0] = CMDLINEMAGIC;
- + CMDLINE[1] = cmdline - LINUX_BOOTSECTOR;
- + linux_cmdline(cmdline);
- + while (*cmdline) putchar(*cmdline++);
- + printf("\r\n");
- + /* Kernel image will be loaded to address 0x10000; it will automatically
- + be relocated to 0x100000 by the setup code */
- + read_size = NFS_READ_SIZE;
- + count = 16*BOOTHEADER.syssize;
- + addr = LINUX_IMAGE_ADDR;
- + printf("Loading compressed kernel image");
- + while (count >= 16) {
- + if (read_size > count) read_size = count;
- + if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, kernel_handle,
- + offset, read_size, addr)) != read_size) {
- + if (err < 0) goto readerr;
- + if (read_size-err >= 16)
- + goto bootmenu; }
- + if (!(offset & 0x3C00)) putchar('.');
- + offset += err;
- + count -= err;
- + addr += err; }
- + /* Linux wants to mount swapspace and rootfilesystem by itself; so unmount */
- + /* all mounted NFS filesystems */
- + nfs_umountall(ARP_ROOTSERVER, root_mount_port);
- + if (arptable[ARP_SWAPSERVER].ipaddr &&
- + arptable[ARP_SWAPSERVER].ipaddr != arptable[ARP_ROOTSERVER].ipaddr)
- + nfs_umountall(ARP_SWAPSERVER, swap_mount_port);
- + /* Linux kernel has to be started in real-mode */
- + printf(" \r\nStarting...\r\n");
- + start_linux();
- + /* printf("*** %s execute failure ***\n",kernel); */
- + goto bootmenu;
- +}
- +
- +int linux_tftp(int block,unsigned char *data,int len)
- +{
- + extern int jmp_bootmenu[10];
- + static enum {Munknown,Mlinear,Mtagged,Mreading} mode = Munknown;
- + static unsigned char *addr,*execaddr,*hdraddr;
- + static struct imgheader {
- + unsigned long magic;
- + unsigned long flags;
- + struct {unsigned short bx,ds; } location;
- + struct {unsigned short ip,cs; } execaddr; } *imgheader;
- + static struct segheader {
- + unsigned long flags;
- + unsigned long loadaddr;
- + unsigned long imglength;
- + unsigned long memlength; } *segheader;
- + static int imglen,headerlen;
- + static unsigned char *last0,*last1;
- + static int lastchunk;
- +
- + if (block == 1) {
- + lastchunk = 0;
- + if (*((unsigned long *)data) == 0x1B031336l) {
- + imgheader = (struct imgheader *)((unsigned long)
- + (((unsigned short *)data)[5])*16 +
- + ((unsigned short *)data)[4]);
- + segheader = (struct segheader *)imgheader;
- + last1 = (last0 = (unsigned char *)imgheader) + 0x200;
- + bcopy(data,imgheader,len);
- + headerlen = (imgheader->flags & 0x0F)*4 +
- + (imgheader->flags & 0xF0)/4;
- + execaddr = *(unsigned char **)&imgheader->execaddr;
- + hdraddr = *(unsigned char **)&imgheader->location;
- + mode = Mtagged;
- + return(1); }
- + else if (((unsigned short *)data)[255] == 0xAA55) {
- + bcopy(data,(char *)0x7C00,len);
- + execaddr = hdraddr = (unsigned char *)0x07C00000l;
- + mode = Mlinear;
- + addr = (char *)0x10000l;
- + return(1); }
- + return(0); }
- + else {
- + int i,datalen = len;
- + if (mode == Mlinear) {
- + bcopy(data,addr,datalen);
- + if ((unsigned long)(addr += 0x200) >= 0x98000l)
- + addr = (unsigned char *)0x100000l; }
- + else if (mode == Mtagged) {
- + tag:
- + do {
- + if (lastchunk)
- + goto launch;
- + segheader = (struct segheader *)((char *)segheader + headerlen);
- + imglen = segheader->imglength;
- + headerlen = (segheader->flags & 0x0F)*4 +
- + (segheader->flags & 0xF0)/4;
- + if ((i = segheader->flags & 0x03000000l) == 0)
- + addr = (unsigned char *)segheader->loadaddr;
- + else if (i == 0x01000000l)
- + addr = last1 + segheader->loadaddr;
- + else if (i == 0x02000000l) {
- + extern unsigned short memsize(void);
- + addr = (unsigned char *)(memsize()*1024l+0x100000l)
- + - segheader->loadaddr; }
- + else
- + addr = last0 - segheader->loadaddr;
- + last1 = (last0 = addr) + segheader->memlength;
- + if (segheader->flags & 0x04000000l) lastchunk = 1;
- + } while (imglen <= 0);
- + mode = Mreading;
- + goto reading; }
- + else if (mode == Mreading) {
- + reading:
- + if ((i = imglen) > datalen) i = datalen;
- + bcopy(data,addr,i);
- + datalen -= i; data += i;
- + addr += i;
- + if ((imglen -= i) <= 0) {
- + mode = Mtagged;
- + if (datalen > 0) goto tag; }
- + return(1); }
- + else
- + return(0); }
- + if (len < 0x200) {
- + extern void xstart(char *,char *,char *);
- + launch:
- + xstart(execaddr,hdraddr,(char *)0x99000000l);
- + longjmp(jmp_bootmenu,1); }
- + return(1);
- +}
- diff -u -r -N netboot-freebsd-for-linux/main.c netboot-freebsd/main.c
- --- netboot-freebsd-for-linux/main.c Fri Sep 8 10:59:08 1995
- +++ netboot-freebsd/main.c Wed Sep 27 20:26:44 1995
- @@ -28,6 +28,10 @@
- extern int packetlen, rpc_id;
- char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
- +extern int load_linux(int root_mount_port,int swap_mount_port,
- + int root_nfs_port,char *kernel_handle);
- +extern int linux_tftp(int block,unsigned char *data,int len);
- +
- /**************************************************************************
- MAIN - Kick off routine
- **************************************************************************/
- @@ -37,6 +41,7 @@
-
- main()
- {
- + extern char *linux_add_cmdline();
- int c;
- char *p;
- extern char edata[], end[];
- @@ -56,13 +61,14 @@
- }
- #endif
- gateA20();
- - printf("\r\nBOOTP/TFTP/NFS bootstrap loader ESC for menu\n\r");
- - printf("\r\nSearching for adapter...");
- + printf("\r\nBOOTP/TFTP/NFS bootstrap loader ESC for menu\n\r"
- + "\r\nSearching for adapter...");
- if (!eth_probe()) {
- printf("No adapter found.\r\n");
- exit(0);
- }
- kernel = DEFAULT_BOOTFILE;
- + linux_add_cmdline(0); /* clear linux cmdline */
- while (1) {
- if (setjmp(jmp_bootmenu))
- bootmenu();
- @@ -72,6 +78,37 @@
- }
-
- /**************************************************************************
- +DOMOUNT - Try to mount FS
- +**************************************************************************/
- +domount(char *s,int *port,int *mount_port,char *hostnam,char *fh,int arpserver,
- + struct sockaddr_in *in_saddr,struct nfs_args *args,char *fnam,
- + char *newfh)
- +{
- + int err;
- + *port = rpclookup(arpserver, PROG_NFS, 2);
- + *mount_port = rpclookup(arpserver, PROG_MOUNT, 1);
- + if ((*port == -1) || (*mount_port == -1)) {
- + printf("Unable to get %s NFS/MOUNT ports\r\n",s);
- + bootmenu:
- + longjmp(jmp_bootmenu,1); }
- + if (err = nfs_mount(arpserver, *mount_port, hostnam, fh)) {
- + printf("Unable to mount %s filesystem: ",s);
- + nfserr:
- + nfs_err(err);
- + goto bootmenu; }
- + in_saddr->sin_len = sizeof(struct sockaddr_in);
- + in_saddr->sin_family = AF_INET;
- + in_saddr->sin_port = htons(*port);
- + in_saddr->sin_addr.s_addr = htonl(arptable[arpserver].ipaddr);
- + args->timeo = 10;
- + args->retrans = 100;
- + if (err = nfs_lookup(arpserver,*port,fh,fnam,newfh)) {
- + printf("Unable to open %s: ",fnam);
- + goto nfserr; }
- + return;
- +}
- +
- +/**************************************************************************
- LOAD - Try to get booted
- **************************************************************************/
- load()
- @@ -104,6 +141,7 @@
- printf("\r\nSearching for server...\r\n");
- if (!bootp()) {
- printf("No Server found.\r\n");
- + bootmenu:
- longjmp(jmp_bootmenu,1);
- }
- }
- @@ -117,16 +155,31 @@
- #endif
-
- /* Now use TFTP to load configuration file */
- +#if defined(PRIORIZEBOOTPKERNEL) && !defined(BOOTPKERNELONLY)
- + printf(" \r\nLoading %s... ",kernel);
- + if (!tftp(kernel)) {
- +#endif
- +#ifndef BOOTPKERNELONLY
- sprintf(cfg,"cfg.%I",arptable[ARP_CLIENT].ipaddr);
- - printf("Loading %s...\r\n",cfg);
- + printf(" \r\nLoading %s... ",cfg);
- if (!tftp(cfg)) {
- sprintf(cfg,"/tftpboot/cfg.%I",arptable[ARP_CLIENT].ipaddr);
- - printf("Loading %s...\r\n",cfg);
- + printf(" \r\nLoading %s... ",cfg);
- if (!tftp(cfg)) {
- - printf("Unable to load config file.\r\n");
- - longjmp(jmp_bootmenu,1);
- - }
- - }
- +#endif
- +#ifndef PRIORIZEBOOTPKERNEL
- + printf(" \r\nLoading %s... ",kernel);
- + if (!tftp(kernel)) {
- +#endif
- + printf("Unable to load config file.\r\n");
- + goto bootmenu;
- +#if !defined(PRIORIZEBOOTPKERNEL) || \
- + defined(PRIORIZEBOOTPKERNEL) && !defined(BOOTPKERNELONLY)
- + }
- +#endif
- +#ifndef BOOTPKERNELONLY
- + } }
- +#endif
-
- #ifdef MDEBUG
- printf("\n=>>"); getchar();
- @@ -149,7 +202,7 @@
- /* Check to make sure we've got a rootfs */
- if (!arptable[ARP_ROOTSERVER].ipaddr) {
- printf("No ROOT filesystem server!\r\n");
- - longjmp(jmp_bootmenu,1);
- + goto bootmenu;
- }
-
- /* Fill in nfsdiskless.myif */
- @@ -179,79 +232,36 @@
- /* Lookup NFS/MOUNTD ports for SWAP using PORTMAP */
- if (arptable[ARP_SWAPSERVER].ipaddr) {
- char swapfs_fh[32], swapfile[32];
- - swap_nfs_port = rpclookup(ARP_SWAPSERVER, PROG_NFS, 2);
- - swap_mount_port = rpclookup(ARP_SWAPSERVER, PROG_MOUNT, 1);
- - if ((swap_nfs_port == -1) || (swap_mount_port == -1)) {
- - printf("Unable to get SWAP NFS/MOUNT ports\r\n");
- - longjmp(jmp_bootmenu,1);
- - }
- - if (err = nfs_mount(ARP_SWAPSERVER, swap_mount_port,
- - nfsdiskless.swap_hostnam, &swapfs_fh)) {
- - printf("Unable to mount SWAP filesystem: ");
- - nfs_err(err);
- - longjmp(jmp_bootmenu,1);
- - }
- sprintf(swapfile,"swap.%I",arptable[ARP_CLIENT].ipaddr);
- - if (err = nfs_lookup(ARP_SWAPSERVER, swap_nfs_port,
- - &swapfs_fh, swapfile, &nfsdiskless.swap_fh)) {
- - printf("Unable to open %s: ",swapfile);
- - nfs_err(err);
- - longjmp(jmp_bootmenu,1);
- - }
- - nfsdiskless.swap_saddr.sin_len = sizeof(struct sockaddr_in);
- - nfsdiskless.swap_saddr.sin_family = AF_INET;
- - nfsdiskless.swap_saddr.sin_port = htons(swap_nfs_port);
- - nfsdiskless.swap_saddr.sin_addr.s_addr =
- - htonl(arptable[ARP_SWAPSERVER].ipaddr);
- - nfsdiskless.swap_args.timeo = 10;
- - nfsdiskless.swap_args.retrans = 100;
- - }
- + domount("SWAP",&swap_nfs_port,&swap_mount_port,nfsdiskless.swap_hostnam,
- + swapfs_fh,ARP_SWAPSERVER,&nfsdiskless.swap_saddr,
- + &nfsdiskless.swap_args,swapfile,nfsdiskless.swap_fh); }
-
- /* Lookup NFS/MOUNTD ports for ROOT using PORTMAP */
- - root_nfs_port = rpclookup(ARP_ROOTSERVER, PROG_NFS, 2);
- - root_mount_port = rpclookup(ARP_ROOTSERVER, PROG_MOUNT, 1);
- - if ((root_nfs_port == -1) || (root_mount_port == -1)) {
- - printf("Unable to get ROOT NFS/MOUNT ports\r\n");
- - longjmp(jmp_bootmenu,1);
- - }
- - if (err = nfs_mount(ARP_ROOTSERVER, root_mount_port,
- - nfsdiskless.root_hostnam, &nfsdiskless.root_fh)) {
- - printf("Unable to mount ROOT filesystem: ");
- - nfs_err(err);
- - longjmp(jmp_bootmenu,1);
- - }
- - nfsdiskless.root_saddr.sin_len = sizeof(struct sockaddr_in);
- - nfsdiskless.root_saddr.sin_family = AF_INET;
- - nfsdiskless.root_saddr.sin_port = htons(root_nfs_port);
- - nfsdiskless.root_saddr.sin_addr.s_addr =
- - htonl(arptable[ARP_ROOTSERVER].ipaddr);
- - nfsdiskless.root_args.timeo = 10;
- - nfsdiskless.root_args.retrans = 100;
- + domount("ROOT",&root_nfs_port,&root_mount_port,nfsdiskless.root_hostnam,
- + nfsdiskless.root_fh,ARP_ROOTSERVER,&nfsdiskless.root_saddr,
- + &nfsdiskless.root_args,*kernel == '/' ? kernel+1 : kernel,
- + kernel_handle);
- nfsdiskless.root_time = 0;
-
- - if (err = nfs_lookup(ARP_ROOTSERVER, root_nfs_port,
- - &nfsdiskless.root_fh, *kernel == '/' ? kernel+1 : kernel,
- - &kernel_handle)) {
- - printf("Unable to open %s: ",kernel);
- - nfs_err(err);
- - longjmp(jmp_bootmenu,1);
- - }
- -
- /* Load the kernel using NFS */
- printf("Loading %s...\r\n",kernel);
- if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, &kernel_handle, 0,
- sizeof(struct exec), &head)) < 0) {
- printf("Unable to read %s: ",kernel);
- + nfserr:
- nfs_err(err);
- - longjmp(jmp_bootmenu,1);
- + goto bootmenu;
- }
- - if (N_BADMAG(head)) {
- + if (N_BADMAG(head) &&
- + !load_linux(root_mount_port,swap_mount_port,
- + root_nfs_port,kernel_handle)) {
- printf("Bad executable format!\r\n");
- - longjmp(jmp_bootmenu, 1);
- + goto bootmenu;
- }
- loadpoint = (char *)0x100000;
- offset = N_TXTOFF(head);
- - printf("text=0x%X, ",head.a_text);
- + /* printf("text=0x%X, ",head.a_text); */
- while (head.a_text > 0) {
- read_size = head.a_text > NFS_READ_SIZE ?
- NFS_READ_SIZE : head.a_text;
- @@ -259,10 +269,10 @@
- &kernel_handle, offset, read_size, loadpoint)) !=
- read_size) {
- if (err < 0) {
- - printf("Unable to read text: ");
- + /* printf("Unable to read text: "); */
- nfs_err(err);
- }
- - longjmp(jmp_bootmenu, 1);
- + goto bootmenu;
- }
- loadpoint += err;
- head.a_text -= err;
- @@ -270,7 +280,7 @@
- }
- while (((int)loadpoint) & CLOFSET)
- *(loadpoint++) = 0;
- - printf("data=0x%X, ",head.a_data);
- + /* printf("data=0x%X, ",head.a_data); */
- while (head.a_data > 0) {
- read_size = head.a_data > NFS_READ_SIZE ?
- NFS_READ_SIZE : head.a_data;
- @@ -278,19 +288,19 @@
- &kernel_handle, offset, read_size, loadpoint)) !=
- read_size) {
- if (err < 0) {
- - printf("Unable to read data: ");
- + /* printf("Unable to read data: "); */
- nfs_err(err);
- }
- - longjmp(jmp_bootmenu, 1);
- + goto bootmenu;
- }
- loadpoint += err;
- head.a_data -= err;
- offset += err;
- }
- - printf("bss=0x%X, ",head.a_bss);
- + /* printf("bss=0x%X, ",head.a_bss); */
- while(head.a_bss--) *(loadpoint++) = 0;
-
- - printf("entry=0x%X.\n\r",head.a_entry);
- + /* printf("entry=0x%X.\n\r",head.a_entry); */
-
- /* Jump to kernel */
- bootinfo.bi_version = BOOTINFO_VERSION;
- @@ -298,7 +308,7 @@
- bootinfo.bi_nfs_diskless = &nfsdiskless;
- kernelentry = (void *)(head.a_entry & 0x00FFFFFF);
- (*kernelentry)(0,NODEV,0,0,0,&bootinfo,0,0,0);
- - printf("*** %s execute failure ***\n",kernel);
- + /* printf("*** %s execute failure ***\n",kernel); */
- }
-
- /**************************************************************************
- @@ -406,42 +416,50 @@
- struct tftp_t *tr;
- int retry = MAX_TFTP_RETRIES;
- static unsigned short isocket = 2000;
- - unsigned short osocket = TFTP;
- - unsigned short len, block=1;
- + unsigned short osocket;
- + unsigned short len,sndlen,block=1,i;
- struct tftp_t tp;
- int code;
- isocket++;
- tp.opcode = htons(TFTP_RRQ);
- - len = (sprintf((char *)tp.u.rrq,"%s%c%s",name,0,"octet")
- - - ((char *)&tp)) + 1;
- - while(retry--) {
- - if (!udp_transmit(arptable[ARP_SERVER].ipaddr, isocket, osocket,
- - len, &tp)) return(0);
- - if (await_reply(AWAIT_TFTP, isocket, NULL)) {
- + sndlen = len = (sprintf((char *)tp.u.rrq,"%s%c%s",name,0,"octet")
- + - ((char *)&tp)) + 1;
- + while(block == 1 && retry--) {
- + if (!udp_transmit(arptable[ARP_SERVER].ipaddr, isocket, TFTP,
- + sndlen, &tp)) return(0);
- + while (await_reply(AWAIT_TFTP, isocket, NULL)) {
- tr = (struct tftp_t *)&packet[ETHER_HDR_SIZE];
- if (tr->opcode == ntohs(TFTP_ERROR)) {
- printf("TFTP error %d (%s)\r\n",
- - ntohs(tr->u.err.errcode),
- - tr->u.err.errmsg);
- - return(0);
- - } /* ACK PACKET */
- + ntohs(tr->u.err.errcode),
- + tr->u.err.errmsg);
- + return(0); } /* ACK PACKET */
- if (tr->opcode != ntohs(TFTP_DATA)) return(0);
- + osocket = ntohs(tr->udp.src);
- tp.opcode = htons(TFTP_ACK);
- tp.u.ack.block = tr->u.data.block;
- - udp_transmit(arptable[ARP_SERVER].ipaddr, isocket,
- - osocket, TFTP_MIN_PACKET_SIZE, &tp);
- len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
- - if (len >= 512) {
- - printf("Config file too large.\r\n");
- - config_buffer[0] = 0;
- - return(0);
- - } else {
- - bcopy(tr->u.data.download, config_buffer, len);
- - config_buffer[len] = 0;
- - }
- - return(1);
- - }
- - }
- + i = ntohs(tr->u.data.block);
- + if (i < block) continue;
- + else if (i > block) return(0);
- + udp_transmit(arptable[ARP_SERVER].ipaddr, isocket,
- + osocket, sndlen = TFTP_MIN_PACKET_SIZE, &tp);
- + if (block == 1) {
- + if (len >= 512) {
- + if (((unsigned short *)tr->u.data.download)[255] != 0xAA55 &&
- + *((unsigned long *)tr->u.data.download) != 0x1B031336l) {
- + config_buffer[0] = 0;
- + return(0); }
- + else
- + printf("Tagged file format"); }
- + else {
- + bcopy(tr->u.data.download, config_buffer, len);
- + config_buffer[len] = 0;
- + return(1); } }
- + if (!linux_tftp(block++,tr->u.data.download,len)) {
- + return(0); }
- + if (len < 512)
- + return(0); } }
- return(0);
- }
-
- @@ -462,8 +480,10 @@
- while(retry--) {
- udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
- sizeof(struct bootp_t), &bp);
- - if (await_reply(AWAIT_BOOTP, 0, NULL))
- - return(1);
- + if (await_reply(AWAIT_BOOTP, 0, NULL)) {
- + extern char *bootphdr;
- + bcopy(&packet[ETHER_HDR_SIZE],bootphdr,packetlen-ETHER_HDR_SIZE);
- + return(1); }
- bp.bp_secs = htons((currticks()-starttime)/20);
- }
- return(0);
- @@ -573,26 +593,18 @@
- if (bcompare(p, rfc1048_cookie, 4)) { /* RFC 1048 header */
- p += 4;
- while(p < end) {
- - switch (*p) {
- - case RFC1048_PAD:
- - p++;
- - continue;
- - case RFC1048_END:
- - p = end;
- - continue;
- - case RFC1048_NETMASK:
- - bcopy(p+2,&netmask,4);
- - break;
- - case RFC1048_HOSTNAME:
- - bcopy(p+2, &nfsdiskless.my_hostnam, TAG_LEN(p));
- - hostnamelen = (TAG_LEN(p) + 3) & ~3;
- - break;
- - default:
- + unsigned char c = *p;
- + if (c == RFC1048_PAD) {p++; continue;}
- + else if (c == RFC1048_END) {p = end; continue; }
- + else if (c == RFC1048_NETMASK) {bcopy(p+2,&netmask,4); }
- + else if (c == RFC1048_HOSTNAME) {
- + bcopy(p+2,&nfsdiskless.my_hostnam,TAG_LEN(p));
- + hostnamelen = (TAG_LEN(p)+3)&~3; }
- + else {
- printf("Unknown RFC1048-tag ");
- for(q=p;q<p+2+TAG_LEN(p);q++)
- printf("%x ",*q);
- - printf("\n\r");
- - }
- + printf("\n\r"); }
- p += TAG_LEN(p) + 2;
- }
- }
- diff -u -r -N netboot-freebsd-for-linux/netboot.h netboot-freebsd/netboot.h
- --- netboot-freebsd-for-linux/netboot.h Thu Sep 7 19:54:14 1995
- +++ netboot-freebsd/netboot.h Tue Sep 26 16:55:45 1995
- @@ -46,7 +46,7 @@
- #endif
-
- #ifndef TIMEOUT /* Inter-packet retry in ticks 18/sec */
- -#define TIMEOUT 20
- +#define TIMEOUT 30
- #endif
-
- #ifndef NULL
- @@ -129,6 +129,7 @@
- #define PORTMAP_LOOKUP 3
-
- #define MOUNT_ADDENTRY 1
- +#define MOUNT_UMNTALL 4
- #define NFS_LOOKUP 4
- #define NFS_READ 6
-
- diff -u -r -N netboot-freebsd-for-linux/ns8390.c netboot-freebsd/ns8390.c
- --- netboot-freebsd-for-linux/ns8390.c Sat Sep 9 00:23:55 1995
- +++ netboot-freebsd/ns8390.c Tue Sep 26 16:57:22 1995
- @@ -310,7 +310,7 @@
- }
- }
- eth_pio_read(0, romdata, 16);
- - printf("\r\nNE1000/NE2000 base 0x%x, addr ", eth_nic_base);
- + printf("\r\nNE*000 base 0x%x, addr ", eth_nic_base);
- for (i=0; i<6; i++) {
- printf("%b",(int)(arptable[ARP_CLIENT].node[i] = romdata[i
- + ((eth_flags & FLAG_16BIT) ? i : 0)]));
- diff -u -r -N netboot-freebsd-for-linux/rpc.c netboot-freebsd/rpc.c
- --- netboot-freebsd-for-linux/rpc.c Thu Sep 7 18:58:37 1995
- +++ netboot-freebsd/rpc.c Wed Sep 27 20:14:38 1995
- @@ -80,6 +80,37 @@
- return(-1);
- }
-
- +/***************************************************************************
- +
- +NFS_UMNTALL: Unmount all NFS Filesystem
- +
- +***************************************************************************/
- +nfs_umountall(server, port)
- + int server;
- + int port;
- +{
- + struct rpc_t buf, *rpc;
- + char *rpcptr;
- + int retries = MAX_RPC_RETRIES;
- + rpcptr = sprintf(&buf.u.data,"%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L",
- + rpc_id, MSG_CALL, 2, PROG_MOUNT, 1, MOUNT_UMNTALL,
- + 1, hostnamelen + 28,0,&nfsdiskless.my_hostnam,0,0,2,0,0,0,0);
- + while(retries--) {
- + udp_transmit(arptable[server].ipaddr, RPC_SOCKET,
- + port, rpcptr - (char *)&buf, &buf);
- + if (await_reply(AWAIT_RPC, rpc_id, NULL)) {
- + rpc = (struct rpc_t *)&packet[ETHER_HDR_SIZE];
- + if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
- + rpc->u.reply.astatus || rpc->u.reply.data[0]) {
- + rpc_err(rpc);
- + return(-(ntohl(rpc->u.reply.data[0])));
- + } else {
- + return(0);
- + }
- + }
- + }
- + return(-1);
- +}
-
- /***************************************************************************
-
- @@ -151,7 +182,7 @@
- } else {
- rlen = ntohl(rpc->u.reply.data[18]);
- if (len < rlen) rlen = len;
- - if (len > rlen) printf("short read\r\n");
- +/* if (len > rlen) printf("short read\r\n"); */
- bcopy(&rpc->u.reply.data[19], buffer, rlen);
- return(rlen);
- }
- @@ -178,10 +209,11 @@
- nfs_err(err)
- int err;
- {
- - err = -err;
- - if (err == NFSERR_PERM) printf("Not owner");
- - else if (err == NFSERR_NOENT) printf("No such file or directory");
- - else if (err == NFSERR_ACCES) printf("Permission denied");
- - else printf("Error %d",err);
- - printf("\r\n");
- + printf(
- +#ifndef TIGHTMEMORY
- + err == -NFSERR_PERM ? "Not owner\r\n" :
- + err == -NFSERR_NOENT ? "No such file or directory\r\n" :
- + err == -NFSERR_ACCES ? "Permission denied\r\n" :
- +#endif
- + "Error %d\n\n",-err);
- }
- diff -u -r -N netboot-freebsd-for-linux/start2.S netboot-freebsd/start2.S
- --- netboot-freebsd-for-linux/start2.S Fri Sep 8 11:04:11 1995
- +++ netboot-freebsd/start2.S Wed Sep 27 19:17:53 1995
- @@ -1,5 +1,9 @@
- -
- -#define STACKADDR 0xe000 /* Needs to be end of bss + stacksize */
- +/* Stack needs to be end of bss + stacksize, but not exceeding lower 640kB */
- +#if RELOC+0xE000 > 0xA0000
- +#define STACKADDR (0xA0000-RELOC)
- +#else
- +#define STACKADDR 0xE000
- +#endif
- #define KERN_CODE_SEG 0x08
- #define KERN_DATA_SEG 0x10
- #define REAL_MODE_SEG 0x18
- @@ -89,6 +93,7 @@
- #endif
- 1:
- nop
- +
- mov %cs,%ax
- mov %ax,%ds
- mov %ax,%es
- @@ -98,6 +103,7 @@
- mov %eax,%esp
- opsize
- call _real_to_prot
- +
- call _main
- .globl _exit
- .globl exit
- @@ -125,8 +131,8 @@
- .globl currticks
- currticks:
- _currticks:
- - push %ebp
- - mov %esp,%ebp
- +/* push %ebp
- + mov %esp,%ebp */
- push %ecx
- push %edx
- xor %edx,%edx
- @@ -141,7 +147,7 @@
- or %ecx,%eax
- pop %edx
- pop %ecx
- - pop %ebp
- +/* pop %ebp */
- ret
-
- /**************************************************************************
- @@ -176,8 +182,8 @@
- .globl getchar
- getchar:
- _getchar:
- - push %ebp
- - mov %esp,%ebp
- +/* push %ebp
- + mov %esp,%ebp */
- push %ebx
- call _prot_to_real
- movb $0x0,%ah
- @@ -188,7 +194,7 @@
- xor %eax,%eax
- movb %bl,%al
- pop %ebx
- - pop %ebp
- +/* pop %ebp */
- ret
-
- /**************************************************************************
- @@ -198,8 +204,8 @@
- .globl iskey
- iskey:
- _iskey:
- - push %ebp
- - mov %esp,%ebp
- +/* push %ebp
- + mov %esp,%ebp */
- push %ebx
- call _prot_to_real
- xor %ebx,%ebx
- @@ -214,10 +220,86 @@
- xor %eax,%eax
- movb %bl,%al
- pop %ebx
- - pop %ebp
- +/* pop %ebp */
- ret
-
-
- +
- +/**************************************************************************
- +MEMSIZE - Determine size of extended memory
- +**************************************************************************/
- +
- + .globl _memsize
- + .globl memsize
- +memsize:
- +_memsize:
- + push %ebx
- + call _prot_to_real
- + .byte 0xb8
- + .word 0x8800
- + int $0x15
- + mov %ax,%bx
- + opsize
- + call _real_to_prot
- + xor %eax,%eax
- + mov %bx,%ax
- + pop %ebx
- + ret
- +
- +/**************************************************************************
- +START_LINUX - Call linux starter code (real mode)
- +**************************************************************************/
- + .globl _start_linux
- + .globl start_linux
- +start_linux:
- +_start_linux:
- + call _prot_to_real
- + opsize
- + call 1f
- + opsize
- + call _real_to_prot
- + ret
- +1: opsize
- + ljmp $0x9020,$0x0
- +
- + .globl _xstart
- + .globl xstart
- +
- +xstart: /* FIXME: this code is rather ugly! could some x86 programmer please*/
- +_xstart: /* come up with something better (I have no clue of x86 programming)*/
- + pushl %ebx
- + pushl %ecx
- + movw 12(%esp,1),%eax /* ugly self-modifying code! */
- + movw %eax,2f+2
- + movw $0x0,2f+4
- + movw 14(%esp,1),%eax
- + movw %eax,2f+6
- + movl 20(%esp,1),%ecx
- + movl 16(%esp,1),%ebx
- + call _prot_to_real
- + opsize
- + ljmp $(RELOC>>4),$1f-_romstart /* flush cache? */
- +1: nop
- + opsize
- + pushl %ecx /* bootp record */
- + opsize
- + pushl %ebx /* file header */
- + opsize
- + call 2f /* return addr */
- + opsize
- + popl %eax
- + opsize
- + popl %eax
- + opsize
- + call _real_to_prot
- + popl %ecx
- + popl %ebx
- + ret
- +2: opsize
- + ljmp $(RELOC>>4),$3f-_romstart
- +3: opsize
- + ret
- +
- /*
- * C library -- _setjmp, _longjmp
- *
-